package com.sky.service.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private WorkspaceService workspaceService;


    /**
     * 营业额数据统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public TurnoverReportVO getTurnover(LocalDate begin, LocalDate end) {
        //组装数据 日期列表
        ArrayList<LocalDate> dataList = new ArrayList<>();
        dataList.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);//计算日期+1天的日期
            dataList.add(begin);
        }

        //组装营业额列表
        ArrayList<Double> turnOverList = new ArrayList<>();
        for (LocalDate date : dataList) {
            //获取某一天最大时间 最小时间
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            HashMap map = new HashMap<>();
            map.put("begin", beginTime);
            map.put("end", endTime);
            map.put("status", Orders.COMPLETED);//已完成订单
            Double turnOver = orderMapper.sumByMap(map);//营业额数据
            turnOver = (turnOver == null ? 0.0 : turnOver);
            turnOverList.add(turnOver);
        }

        //创建TurnoverReportVO对象
        String dataListStr = StringUtils.join(dataList, ",");
        String turnOverListStr = StringUtils.join(turnOverList, ",");

        return new TurnoverReportVO(dataListStr, turnOverListStr);
    }

    /**
     * 用户统计
     *
     * @param begin 用户创建时间
     * @param end
     * @return
     */
    @Override
    public UserReportVO getUserReport(LocalDate begin, LocalDate end) {
        //组装数据 日期列表
        ArrayList<LocalDate> dataList = new ArrayList<>();
        dataList.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);//计算日期+1天的日期
            dataList.add(begin);
        }

        //组装每日用户总量 新增用户量
        ArrayList<Integer> totalUserList = new ArrayList<>();
        ArrayList<Integer> newUserList = new ArrayList<>();
        for (LocalDate date : dataList) {
            //获取某一天的 开始时间 结束时间
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            log.info("beginTime:{}", beginTime);
            log.info("endTime:{}", endTime);
            //查询当天总用户量 (当天结束时间之前 create_time<endTime)
            HashMap map = new HashMap<>();
            map.put("endTime", endTime);
            Integer totalUser = userMapper.countByMap(map);
            totalUserList.add(totalUser);
            //查询当天新增用户量(当天开始时间之后~当天结束时间之前 beginTime<endTime<endTime)
            map.put("beginTime", beginTime);
            Integer newUser = userMapper.countByMap(map);
            newUserList.add(newUser);
        }


        //封装UserReportVO返回
        String dataListStr = StringUtils.join(dataList, ",");
        String totalUserListStr = StringUtils.join(totalUserList, ",");
        String newUserListStr = StringUtils.join(newUserList, ",");

        return new UserReportVO(dataListStr, totalUserListStr, newUserListStr);
    }

    /**
     * 订单统计
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public OrderReportVO getOrderReport(LocalDate begin, LocalDate end) {
        //组装数据 日期列表
        ArrayList<LocalDate> dataList = new ArrayList<>();
        dataList.add(begin);
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);//计算日期+1天的日期
            dataList.add(begin);
        }

        ArrayList<Integer> orderCountList = new ArrayList<>();//每日订单数，
        ArrayList<Integer> validOrderCountList = new ArrayList<>();//每日有效订单数，
        //获取每日订单总数 每日有效订单数
        for (LocalDate date : dataList) {
            //获取某一天的 开始时间 结束时间
            LocalDateTime beginTime = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(date, LocalTime.MAX);
            //每日总订单数 select * from orders where order_time > beginTime and order_time <endTime
            HashMap map = new HashMap<>();
            map.put("begin", beginTime);
            map.put("end", endTime);
            Integer totalOrderCount = orderMapper.countByMap(map);
            orderCountList.add(totalOrderCount);
            //每日总有效订单数 select * from orders where status = 5 and order_time > beginTime and order_time <endTime
            map.put("status", Orders.COMPLETED);
            Integer validOrderCount = orderMapper.countByMap(map);
            validOrderCountList.add(validOrderCount);
        }

        //获取总订单数 总有效订单数 订单完成率
        Integer totalOrderCount = orderCountList.stream().reduce(Integer::sum).get();
        Integer validOrderCount = validOrderCountList.stream().reduce(Integer::sum).get();
        Double orderCompletionRate = 0.0;
        if (validOrderCount != 0) {
            orderCompletionRate = validOrderCount * 1.0 / totalOrderCount;
        }

        OrderReportVO orderReportVO = new OrderReportVO();
        orderReportVO.setDateList(StringUtils.join(dataList, ","));
        orderReportVO.setOrderCountList(StringUtils.join(orderCountList, ","));
        orderReportVO.setValidOrderCountList(StringUtils.join(validOrderCountList, ","));
        orderReportVO.setValidOrderCount(validOrderCount);
        orderReportVO.setTotalOrderCount(totalOrderCount);
        orderReportVO.setOrderCompletionRate(orderCompletionRate);

        return orderReportVO;

    }

    /**
     * 销量top10
     *
     * @param begin
     * @param end
     * @return
     */
    @Override
    public SalesTop10ReportVO getTop10(LocalDate begin, LocalDate end) {
        //开始时间 结束时间
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        log.info("getTop10beginTime:{}", beginTime);
        log.info("getTop10endTime:{}", endTime);
        HashMap map = new HashMap<>();
        map.put("begin", beginTime);
        map.put("end", endTime);
        //查询出top10的 商品名称和销量
        List<GoodsSalesDTO> goodsSalesDTOList = orderMapper.getSalesTop10ByMap(map);
        log.info("goodsSalesDTOList:{}", goodsSalesDTOList);
        //处理goodsSalesDTOList数据封装到SalesTop10ReportVO
        List<String> nameList = goodsSalesDTOList.stream().map(s -> s.getName()).collect(Collectors.toList());
        List<Integer> numberList = goodsSalesDTOList.stream().map(s -> s.getNumber()).collect(Collectors.toList());

        //封装SalesTop10ReportVO
        SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
        salesTop10ReportVO.setNameList(StringUtils.join(nameList, ','));
        salesTop10ReportVO.setNumberList(StringUtils.join(numberList, ','));

        return salesTop10ReportVO;
    }

    /**
     * 导出运营数据
     *
     * @param response
     */
    @Override
    public void exportBusinessData(HttpServletResponse response) {
        //导出近30天的运营数据
        //开始时间 当前日期-30 结束时间 当前日期-1
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);

        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        //获取近30天营业数据
        BusinessDataVO businessData = workspaceService.getBusinessData(beginTime, endTime);

        //写出文件
        //获取当前class中的excel模板文件,填入数据
        InputStream is =
                this.getClass().
                    getClassLoader().
                    getResourceAsStream("template/运营数据报表模板.xlsx");

        try {
            //获取excel文件对象
            XSSFWorkbook excel = new XSSFWorkbook(is);
            //获取sheet表
            XSSFSheet sheet = excel.getSheetAt(0);
            //1 填充概览数据
            //获取填充位置并填充数据
            sheet.getRow(1).getCell(1).setCellValue(begin + "至" + end);
            sheet.getRow(3).getCell(2).setCellValue(businessData.getTurnover());//营业额
            sheet.getRow(3).getCell(4).setCellValue(businessData.getOrderCompletionRate());//订单完成率
            sheet.getRow(3).getCell(6).setCellValue(businessData.getNewUsers());//新增用户数
            sheet.getRow(4).getCell(2).setCellValue(businessData.getValidOrderCount());//有效订单数
            sheet.getRow(4).getCell(4).setCellValue(businessData.getUnitPrice());//平均客单价

            //2 填充明细数据
            for (int i = 0; i < 30; i++) {
                //每天开始~结束时间
                LocalDate date = begin.plusDays(i);
                LocalDateTime everyBeginTime = LocalDateTime.of(date, LocalTime.MIN);//当天开始时间
                LocalDateTime everyEndTime = LocalDateTime.of(date, LocalTime.MAX);//当天结束时间
                //每天的营业数据
                BusinessDataVO everyData = workspaceService.getBusinessData(everyBeginTime, everyEndTime);
                //获取每一行
                XSSFRow row = sheet.getRow(7 + i);
                //填充每一列数据
                row.getCell(1).setCellValue(date.toString());//日期
                row.getCell(2).setCellValue(everyData.getTurnover());//营业额
                row.getCell(3).setCellValue(everyData.getValidOrderCount());//有效订单数
                row.getCell(4).setCellValue(everyData.getOrderCompletionRate());//订单完成率
                row.getCell(5).setCellValue(everyData.getUnitPrice());//平均客单价
                row.getCell(6).setCellValue(everyData.getNewUsers());//新增用户数
            }
            //写出文件
            ServletOutputStream os = response.getOutputStream();
            excel.write(os);
            //释放资源
            os.flush();
            os.close();
            excel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }
}
